package store

import (
	"context"
	baseLog "gitee.com/zaiqiang231/go-base-app/base_app/log"
	baseStore "gitee.com/zaiqiang231/go-base-app/base_app/store"
	"gitee.com/zaiqiang231/zcamp-service-user/app/config"
	"gitee.com/zaiqiang231/zcamp-service-user/app/model"
	"gitee.com/zaiqiang231/zcamp-service-user/app/util"
	"gorm.io/gorm"
	"strconv"
	"time"
)

var (
	//userid构建的list
	redisUserIdMQ = "USER_ACCOUNT_ID"
	//当前uid
	redisUserMaxID = "USER_MAX_ID"
)

// UserIdMqLen 获取uidlist的长度
func UserIdMqLen(ctx context.Context) (int64, error) {
	sz, err := baseStore.GetRedisStore().LLen(ctx, redisUserIdMQ).Result()
	if err != nil {
		baseLog.Errorf("redis llen %v error (%v)", redisUserIdMQ, err)
		return 0, err
	}
	return sz, nil
}

// UserIdGenToMQ 生成uid到list中
func UserIdGenToMQ(ctx context.Context) (uint64, error) {
begin:
	uid, err := incrMaxID(ctx)
	if err != nil {
		baseLog.Errorf("incr redis error (%v)", err)
		return 0, err
	}

	if util.IsVipUid(strconv.FormatUint(uid, 10)) {
		// slowly insert to mysql
		time.Sleep(time.Millisecond * 2)
		goodIdSave(uid)
		goto begin
	} else if uid >= config.GlobalAppConfig.RobotUidStart && uid <= config.GlobalAppConfig.RobotUidEnd { //机器人号段先屏蔽
		goto begin
	} else {
		err = baseStore.GetRedisStore().LPush(ctx, redisUserIdMQ, uid).Err()
		if err != nil {
			baseLog.Errorf("lpush redis error (%v)", err)
			return 0, err
		}
		return uid, nil
	}
}

func incrMaxID(ctx context.Context) (uint64, error) {
IdGen:
	uid, err := baseStore.GetRedisStore().IncrBy(ctx, redisUserMaxID, 1).Result()

	if err != nil {
		baseLog.Errorf("redis incr %v error (%v)", redisUserMaxID, err)
		return 0, err
	}

	if uid < config.GlobalAppConfig.DefaultIdBegin {
		err := baseStore.GetRedisStore().Set(ctx, redisUserMaxID, config.GlobalAppConfig.DefaultIdBegin, 0).Err()
		if err != nil {
			baseLog.Errorf("redis incr %v error (%v)", redisUserMaxID, err)
			return 0, err
		}
		goto IdGen
	}

	return uint64(uid), nil
}

func goodIdSave(uid uint64) error {
	var err error
	baseStore.GetDataStore().Execute(func(db *gorm.DB) {
		row := model.UserIdSuper{Uid: uid}
		err = db.Create(&row).Error
	})
	return err
}

// IdGetInMQ 从uidlist里取uid
func IdGetInMQ(ctx context.Context) (int64, error) {
	idStr, err := baseStore.GetRedisStore().RPop(ctx, redisUserIdMQ).Result()
	if err != nil || idStr == "" {
		baseLog.Errorf("redis rpop return nil, mq name: %v", redisUserIdMQ)
		return 0, err
	}

	if uid, err := strconv.ParseInt(idStr, 10, 64); err != nil {
		baseLog.Errorf("parse id %v error", idStr)
		return 0, err
	} else {
		return uid, nil
	}
}
